package com.ninth;



import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;

// bean工厂创建对象
class BeanFactory {

    //读取配置文件，这里把输入流当做是任意一个配置文件的输入流，可实现任意配置文件的读取
    //之前的学习，这里是把读取配置文件的输入流写死了在静态代理块里，就只能是一次性的
    private Properties prop = new Properties();

    BeanFactory(InputStream in) {
        try {
            prop.load(in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //获取一个bean实例,即通过读取配置文件，创建ProxyFactoryBean 的实例
    Object getBean(String name) {
        Object bean = null;
        String beanName = prop.getProperty(name);
        try {
            //获取ProxyFactoryBean的Class对象
            Class<?> aClass = Class.forName(beanName);
            //实例化ProxyFactoryBean的Class对象
            bean = aClass.newInstance();

            //根据配置文件，实例化target 和  advice 对象
            Object target = Class.forName(prop.getProperty(name + ".target")).newInstance();
            Object advice = Class.forName(prop.getProperty(name + ".advice")).newInstance();

            //通过内省，实现对ProxyFactoryBean的属性赋值:它的属性就是两个类对象：private Object target和private Advice advice;
            BeanInfo beanInfo = Introspector.getBeanInfo(aClass);
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
            for (PropertyDescriptor pd : propertyDescriptors) {
                Method writeMethod = pd.getWriteMethod();
                String propertyName = pd.getName();
                if ("target".equals(propertyName)) {
                    writeMethod.invoke(bean, target);
                } else if ("advice".equals(propertyName)) {
                    writeMethod.invoke(bean, advice);
                }
            }

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IntrospectionException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return bean;
    }

}